#include "mainWindow.h"

MainWindow::MainWindow(QWidget *parent) :
	QMainWindow(parent) {

	this->setGeometry(300, 200, 0,0); //ustaw rozmiar okna
	setupMenus(); // konfiguracja menu
	this->setWindowTitle("Jamniki"); // ustaw nazwe glownego okna

	servConn = new ConnectionPlayer();

	bottomWidget = new BottomWidget(this);
	bottomToolBar = new QToolBar();
	bottomToolBar->setMovable(false);
	bottomToolBar->addWidget(bottomWidget);
	addToolBar(Qt::BottomToolBarArea, bottomToolBar);

	leftWidget = new Score(0);
	leftToolBar = new QToolBar();
	leftToolBar->setMovable(false);
	leftToolBar->addWidget(leftWidget);
	addToolBar(Qt::LeftToolBarArea, leftToolBar);


	rightWidget = new RightWidget(this);
	rightToolBar = new QToolBar();
	rightToolBar->setMovable(false);
	rightToolBar->addWidget(rightWidget);
	addToolBar(Qt::RightToolBarArea, rightToolBar);
	rightToolBar->setEnabled(false);

	view = new View(); // utworz widok
	this->setCentralWidget(view); // ustaw view jako centralny widget
	view->setCacheMode(QGraphicsView::CacheBackground);
	view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
	view->setFixedHeight(450);
	view->setFixedWidth(450);
	food = NULL;
	player = NULL;
	scene = new QGraphicsScene(); // utworz nowa scene
	clearScene(false);
	connect(&timer, SIGNAL(timeout()), view, SLOT(update()));
	connect(bottomWidget, SIGNAL(connectClicked(QString, QString)), this, SLOT(connectToServer(QString, QString)));
	connect(servConn, SIGNAL(stateChanged(QAbstractSocket::SocketState)), bottomWidget, SLOT (onConnStateChanged(QAbstractSocket::SocketState)));
	connect(servConn, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT (onConnStateChanged(QAbstractSocket::SocketState)));
	connect(servConn, SIGNAL (newMessage(ConnectionPlayer*, QString, QStringList)), this, SLOT(onNewMessage(ConnectionPlayer*,QString, QStringList)));
	connect(bottomWidget, SIGNAL(readyClicked()), this, SLOT(onReadyClicked()));
	connect(bottomWidget, SIGNAL(leaveClicked()), this, SLOT(onLeaveClicked()));

	view->setScene(scene);
	view->show(); // pokaz widok

	setMaximumSize(size());
	setMinimumSize(size());
}

void MainWindow::onReadyClicked() {
	if (servConn->getSitting()) {
		servConn->sendMessage("READY");
	} else {
		servConn->sendMessage("SIT");
	}
}

void MainWindow::onLeaveClicked() {
	servConn->sendMessage("LEAVE");
}

void MainWindow::onConnStateChanged(QAbstractSocket::SocketState socketState) {
	if (socketState == QAbstractSocket::ConnectedState) {
		InputDialog * nickDialog = new InputDialog("Your nick", "Set");
		connect(nickDialog, SIGNAL(valueSet(QString)), this, SLOT (joinGame(QString)));
		rightToolBar->setEnabled(true);
	} else if (socketState == QAbstractSocket::UnconnectedState) {
		rightWidget->clearNicks();
		leftWidget->removeAll();
	}
}

void MainWindow::onNewMessage(ConnectionPlayer* conn, QString cmd, QStringList args) {
	if (cmd == "PLAYERS") {//serwer przesyla nam aktualna liste uzytkownikow
		rightWidget->updateLists(args);
		leftWidget->addPlayersList(args);
	} else if (cmd == "JOIN") {
		rightWidget->addSpectatorNick(args.at(0));
	} else if (cmd == "USED") {//wybrany nick zajety, trzeba wybrac inny
		InputDialog * nickDialog = new InputDialog("Choose another nick", "Set");
		connect(nickDialog, SIGNAL(valueSet(QString)), this, SLOT (changeNick(QString)));
	} else if (cmd == "QUIT") {//nick opuscil gre
		QString nick = args.at(0);
		rightWidget->removeSpectatorNick(nick);
		rightWidget->removePlayerNick(nick);
		leftWidget->removePlayer(nick);

	} else if (cmd == "SIT") {//jakis gracz usiadl
		QString nick = args.at(0);
		rightWidget->removeSpectatorNick(nick);
		rightWidget->addPlayerNick(nick);
		leftWidget->addPlayer(nick);
		if (servConn->getNick()==nick) {
			servConn->setSitting(true);
			bottomWidget->onSit();
		}
	} else if (cmd == "ID") {//ustawia id nadane przez serwer
		int id = args.at(0).toInt();
		servConn->setId(id);
	} else if (cmd == "LEAVE") {//gracz przeszedl do spectatorow
		QString nick = args.at(0);
		rightWidget->removePlayerNick(nick);
		leftWidget->removePlayer(nick);
		rightWidget->addSpectatorNick(nick);
		if (servConn->getNick()==nick) {
			servConn->setSitting(false);
			servConn->setReady(false);
			bottomWidget->onLeave();
		}
	} else if (cmd == "READY") {
		QString nick = args.at(0);
		rightWidget->boldPlayerNick(nick);
		if (servConn->getNick()==nick) {
			servConn->setSitting(true);
			servConn->setReady(true);
			bottomWidget->onReady();
		}
	} else if (cmd == "START") {
		gameState = gameStarted;
		clearScene();
		deletePlayerList();
		deleteFoodList();
	} else if (cmd == "PLAYER") {
		int id = args[0].toInt();
		playerList.append(new Jamnik(id, args.mid(1)));
		scene->addItem(playerList.last());
		if (conn->getId()==id) {
			player = playerList.last();
			connect(view, SIGNAL(keyPressed(int)), player, SLOT(onDirPressed(int)));
			connect(player, SIGNAL(directionChanged(QString)), this, SLOT(onDirectionChanged(QString)));
		}
	} else if (cmd == "FOOD") {
		foodList.append(new Food(args[0]));
		scene->addItem(foodList.last());
	} else if (cmd == "DIR") {
		int id = args[0].toInt();
		playerList[id-1]->changeDirection(args[1]);
	} else if (cmd == "TICK") {
		for (int i = 0; i < playerList.size(); i++) {
			playerList[i]->move();
		}
	}
}

void MainWindow::onDirectionChanged(QString d) {
	//qDebug() << d;
	servConn->sendMessage("DIR", QStringList() << d);
}

void MainWindow::joinGame(QString nick) {

	QStringList args;
	args.append(nick);

	servConn->sendMessage("HELLO", args);
	servConn->setNick(nick);
}

void MainWindow::changeNick(QString nick) {
	QStringList args;
	args.append(nick);

	servConn->sendMessage("NICK", args);
	servConn->setNick(nick);
}

void MainWindow::connectToServer(QString host, QString port) {
	if (servConn->state() != QAbstractSocket::ConnectedState) {
		int p = port.toInt();
		if (p > 0) {
			servConn->connectToHost(host, p);
		}
	} else {
		servConn->disconnectFromHost();
		rightWidget->clearNicks();
		servConn->resetData();
	}

}

void MainWindow::onFoodEaten(QPoint xy) {
	//wyszukiwanie fooda ktory zostal zjedzony jesli foodCount > 1
	food->randomXY(20, 20);
	while (player->iAmHere(food)) {
		food->randomXY(20, 20);
	}
	Jamnik::foodSetInsert(food);
}

void MainWindow::startServer(QString port)
{
	int p = port.toInt();//jesli fail zwraca 0
	if (p == 0) {
		setWindowTitle("Wrong port :(");
	} else {
		setWindowTitle("Server started on port: " + port);
		server = new Server();
		server->start(p);
		servConn->connectToHost("localhost", p);
		rightToolBar->setEnabled(true);
	}
}

void MainWindow::onHostGame() {
	InputDialog *portDialog = new InputDialog("Server port", "Start server");
	connect(portDialog, SIGNAL(valueSet(QString)), this, SLOT(startServer(QString)));//startuje server z ustawionym portem
}

void MainWindow::clearScene(bool deleteScene) {
	if (deleteScene && scene != NULL) { //usuwa i dodaje pusta scene
		delete scene;
		scene = new QGraphicsScene();
	}
	//wstawia kwadrat z bialym tlem
	scene->clear();
	scene->addRect(QRect(0, 0, 400, 400), QPen(QColor(Qt::black)), QBrush(
			QColor(Qt::white), Qt::SolidPattern));
	scene->items().at(0)->setZValue(-1);//aby tlo nie zaslanialo pieska
}

void MainWindow::setupMenus() {
	QMenu *fileMenu = menuBar()->addMenu("Plik");

	QAction *newGameAction = fileMenu->addAction("Nowa Gra");
	newGameAction->setShortcut(QKeySequence("Ctrl+N"));

	QAction *serverAction = fileMenu->addAction("Host game");//odpala modalne okno z wyborem portu
	serverAction->setShortcut(QKeySequence("Ctrl+H"));

	QAction *exitAction = fileMenu->addAction("Wyjscie");
	exitAction->setShortcut(QKeySequence("Ctrl+Q"));

	connect(exitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
	connect(newGameAction, SIGNAL(triggered()), this, SLOT(newGame()));//to to moze single player?
	connect(serverAction, SIGNAL(triggered()), this, SLOT(onHostGame()));//odpala serwer i czeka na polaczenie innych
}

void MainWindow::deletePlayerList() {
	for (int i = playerList.size() - 1; i >= 0; i--) {
		delete playerList[i];
		playerList.remove(i);
	}
}

void MainWindow::deleteFoodList() {
	for (int i = foodList.size() - 1; i >= 0; i--) {
		delete foodList[i];
		foodList.remove(i);
	}
}

void MainWindow::deletePlayers() {
	if (player != NULL) {
		/*for (int i = 0; i < settings.getPlayerCount(); ++i) {
		 if (players[i] != NULL)
		 delete players[i];
		 }*/
		//scene->removeItem(players[0]);
		delete player;
	}
}

void MainWindow::createPlayers() {
	player = new Jamnik(1,(QStringList() << "19,8" << "17,8"), false);
	scene->addItem(player);
}

void MainWindow::deleteFood() {
	delete food;
}

void MainWindow::createFood() {

	food = new Food();
	food->randomXY(20, 20);
	while (player->iAmHere(food)) {
		food->randomXY(20, 20);
	}
	Jamnik::foodSet.clear();
	Jamnik::foodSetInsert(food);
	scene->addItem(food);
}

void MainWindow::newGame() {
	clearScene(false);
	createPlayers();
	createFood();

	view->setScene(scene);
	bottomToolBar->setEnabled(false);
	view->setFocus();

	for (int i = 0; i < settings.getPlayerCount(); ++i) {
		connect(&timer, SIGNAL(timeout()), player, SLOT(move()));
		connect(view, SIGNAL(keyPressed(int)), player, SLOT(onDirPressed(int)));
		connect(player, SIGNAL(foodEaten(QPoint)), this, SLOT(onFoodEaten(QPoint)));
	}
	timer.setInterval(settings.getJamnikSpeed());
	timer.start();
}
